package com.zt.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.entity.Coupons;
import com.zt.service.AdminCouponCacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 管理端优惠券缓存服务实现
 * 只处理coupons:开头的键
 */
@Slf4j
@Service
public class AdminCouponCacheServiceImpl implements AdminCouponCacheService {
    
    private static final String ADMIN_COUPON_LIST_KEY = "coupons:admin:list";
    private static final long DEFAULT_TTL_HOURS = 24; // 默认24小时
    private static final long MIN_TTL_HOURS = 1; // 最小1小时
    
    @Autowired
    private StringRedisTemplate couponRedisTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public void cacheAdminCouponList(List<Coupons> coupons) {
        try {
            if (coupons == null || coupons.isEmpty()) {
                log.debug("优惠券列表为空，跳过缓存");
                return;
            }
            
            // 转换为指定格式的JSON
            String couponsJson = convertCouponsToJson(coupons);
            
            // 计算TTL
            long ttlSeconds = calculateCouponListTTL(coupons);
            
            // 缓存到Redis
            couponRedisTemplate.opsForValue().set(ADMIN_COUPON_LIST_KEY, couponsJson, ttlSeconds, TimeUnit.SECONDS);
            
            log.info("管理端优惠券列表已缓存到 {}, 数量: {}, TTL: {}秒", ADMIN_COUPON_LIST_KEY, coupons.size(), ttlSeconds);
        } catch (Exception e) {
            log.error("缓存管理端优惠券列表失败", e);
        }
    }
    
    @Override
    public List<Coupons> getCachedAdminCouponList() {
        try {
            String couponsJson = couponRedisTemplate.opsForValue().get(ADMIN_COUPON_LIST_KEY);
            if (couponsJson != null) {
                List<Coupons> coupons = objectMapper.readValue(couponsJson, new TypeReference<List<Coupons>>() {});
                log.debug("从缓存获取管理端优惠券列表，数量: {}", coupons.size());
                return coupons;
            }
        } catch (Exception e) {
            log.error("获取缓存的管理端优惠券列表失败", e);
        }
        return null;
    }
    
    @Override
    public void clearAdminCouponListCache() {
        try {
            couponRedisTemplate.delete(ADMIN_COUPON_LIST_KEY);
            log.info("已清除管理端优惠券列表缓存: {}", ADMIN_COUPON_LIST_KEY);
        } catch (Exception e) {
            log.error("清除管理端优惠券列表缓存失败", e);
        }
    }
    
    @Override
    public long calculateCouponListTTL(List<Coupons> coupons) {
        if (coupons == null || coupons.isEmpty()) {
            return DEFAULT_TTL_HOURS * 3600;
        }
        
        Date now = new Date();
        long maxTtlSeconds = 0;
        
        for (Coupons coupon : coupons) {
            long ttlSeconds = calculateSingleCouponTTL(coupon, now);
            if (ttlSeconds > maxTtlSeconds) {
                maxTtlSeconds = ttlSeconds;
            }
        }
        
        // 确保至少有最小TTL
        long minTtlSeconds = MIN_TTL_HOURS * 3600;
        return Math.max(maxTtlSeconds, minTtlSeconds);
    }
    
    /**
     * 计算单个优惠券的TTL
     */
    private long calculateSingleCouponTTL(Coupons coupon, Date now) {
        if (coupon.getEndTime() == null) {
            // 没有结束时间，使用默认TTL
            return DEFAULT_TTL_HOURS * 3600;
        }
        
        long endTimeMillis = coupon.getEndTime().getTime();
        long nowMillis = now.getTime();
        
        if (endTimeMillis <= nowMillis) {
            // 已过期，使用最小TTL
            return MIN_TTL_HOURS * 3600;
        }
        
        // 计算到结束时间的秒数
        long ttlSeconds = (endTimeMillis - nowMillis) / 1000;
        
        // 添加一些缓冲时间（1小时）
        ttlSeconds += 3600;
        
        return ttlSeconds;
    }
    
    /**
     * 将优惠券列表转换为指定格式的JSON
     * 格式：[{"id":1,"title":"新人专享券","description":"可用于任意课程","type":1,"amount":20.00,"minSpend":150.00,"startTime":1704067200000,"endTime":1777679999000,"status":1}]
     */
    private String convertCouponsToJson(List<Coupons> coupons) throws Exception {
        return objectMapper.writeValueAsString(coupons);
    }
}
